﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace BreukTrainer.BreukModel
{
    /// <summary>
    /// Klasse om <see cref="Breuk"/> objecten bij te houden
    /// </summary>
    public class BreukContainer
    {
        /// <summary>
        /// Een Collection voor <see cref="Breuk"/>.
        /// </summary>
        private List<Breuk> breuken;
        /// <summary>
        /// Properties voor <see cref="breuken"/>.
        /// </summary>
        /// <returns><see cref="Breuken"/></returns>
        public List<Breuk> Breuken
        {
            get
            {
                return breuken;
            }
            set
            {
                breuken = value;
            }
        }

        /// <summary>
        /// Bepaald hoe de output eruit ziet.
        /// </summary>
        /// <remarks>Strategy</remarks>
        private IBreukContainerFormatter formatter;

        /// <summary>
        /// Property for <see cref="formatter"/>
        /// </summary>
        public IBreukContainerFormatter Formatter
        {
            get 
            {
                return formatter;
            }
            set
            {
                formatter = value;
            }
        }

        /// <summary>
        /// Maakt een nieuwe BreukContainer aan.
        /// </summary>
        public BreukContainer()
        {
            Breuken = new List<Breuk>();
            Formatter = new DefaultFormatter();
        }

        /// <summary>
        /// indexer en shit
        /// </summary>
        /// <param name="index">de index idioot</param>
        /// <returns>een Breuk object</returns>
        public Breuk this[int index]
        {
            get
            {
                return Get(index);
            }
            set
            {
                Breuk b = Get(index);
                b = value;
            }
        }

        /// <summary>
        /// Voegt een <see cref="Breuk"/> toe aan de List.
        /// </summary>
        /// <param name="breuk">Een <see cref="Breuk"/>.</param>
        public virtual void Add(Breuk breuk)
        {
            Breuken.Add(breuk);
        }

        /// <summary>
        /// Verwijdert een <see cref="Breuk"/> uit Breuken. op index n en geeft deze terug.
        /// </summary>
        /// <returns>Een <see cref="Breuk"/>.</returns>
        /// <param name="n">Een <see langword="integer"/> index.</param>
        public Breuk Remove(int n)
        {
            Breuk b = Breuken[n];
            Breuken.RemoveAt(n);
            return b;
        }

        /// <summary>
        /// Geeft de <see cref="Breuk"/> terug op index n.
        /// </summary>
        /// <returns>Een <see cref="Breuk"/>.</returns>
        /// <param name="n">Een <see langword="integer"/> index.</param>
        public Breuk Get(int n)
        {
            return Breuken[n];
        }

        /// <summary>
        /// Verwijderd elke <see cref="Breuk"/> object uit deze container
        /// </summary>
        public void MaakLeeg()
        {
            Breuken.Clear();
        }

        /// <summary>
        /// Geeft een <see cref="Breuk"/> terug welke de som is van alle Breuken.
        /// </summary>
        public Breuk SomAlle()
        {
            Breuk som = new Breuk(0, 1);
            foreach (Breuk b in Breuken)
            {
                som += b;
            }
            return som;
        }

        /// <summary>
        /// Geeft een <see cref="Breuk"/> terug welke het verschil is van alle Breuken.
        /// </summary>
        public Breuk VerschilAlle()
        {
            Breuk verschil = new Breuk(Breuken[0].Teller, Breuken[0].Noemer);
            for (int i = 1; i < Breuken.Count; i++)
            {
                verschil -= (Get(i));
            }
            return verschil;
        }

        /// <summary>
        /// Geeft een <see cref="Breuk"/> terug welke het product is van alle Breuken.
        /// </summary>
        /// <returns><see cref="Breuk"/></returns>
        public Breuk ProductAlle()
        {
            Breuk product = new Breuk(Breuken[0].Teller, Breuken[0].Noemer);
            for (int i = 1; i < Breuken.Count; i++)
            {
                product *= (Get(i));
            }
            return product;
        }

        /// <summary>
        /// Geeft een <see cref="Breuk"/> terug welke de quotient is van alle Breuken.
        /// </summary>
        /// <returns><see cref="Breuk"/></returns>
        public Breuk QuotientAlle()
        {
            Breuk quotient = new Breuk(Breuken[0].Teller, Breuken[0].Noemer);
            for (int i = 1; i < Breuken.Count; i++)
            {
                quotient /= (Get(i));
            }
            return quotient;
        }

        /// <summary>
        /// Geeft een IEnumerable object terug die alle breuken gesorteerd terruggeeft
        /// </summary>
        /// <param name="oplopend">moet het oplopend ja of nee</param>
        /// <returns>een IEnumerable object</returns>
        public IEnumerable<Breuk> Sorteer(bool oplopend)
        {
            if (oplopend)
            {
                return breuken.OrderBy(delegate(Breuk breuk)
                {
                    return breuk.DecimaleWaarde();
                });
            }
            else
            {
                return breuken.OrderByDescending(delegate(Breuk breuk)
                {
                    return breuk.DecimaleWaarde();
                });
            }
        }

        /// <summary>
        /// Geeft een lijst van alle Breuken volgens formatter.
        /// </summary>
        /// <returns>String</returns>
        public string Overzicht()
        {
            return Formatter.FormatBreukContainer(this);
        }

    }
}